#pragma once
#include<iostream>
#include<string>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<cstring>
#include<cerrno>
#include<cstdlib>
#include"Log.hpp"
#include"Common.hpp"
using namespace LogMoudle;
namespace SocketMoudle
{
    const static int defaulted=-1;
    class Socket
    {
        // 基类套接字
    public:
        Socket():_sockfd(defaulted){}
        Socket(int sockfd):_sockfd(sockfd){}
        virtual int SocketOrDie() = 0;
        virtual bool BindOrDie(uint16_t port) = 0;
        virtual bool ListenOrDie(int backlog=10) = 0;
        virtual std::shared_ptr<Socket> Accept(NetAddr*client) = 0;
        virtual int Recv(std::string *in)=0;
        virtual void Close() = 0;
        virtual bool Send(const std::string &out)=0;
        virtual int Connect(std::string& ip,uint16_t port)=0;
        void BuildclientSocket(std::string& ip,uint16_t port){
            //创建套接字
            SocketOrDie();
        }
        int GetSockFd() const { return _sockfd; }
    public:
        void BuildListenSocket(uint16_t port,int backlog=10)
        {
            SocketOrDie();
            BindOrDie(port);
            ListenOrDie(backlog);
        }
        void BuildUdpSocket(uint16_t port,int backlog=10)
        {
            SocketOrDie();
            BindOrDie(port);
        }
    private:
        int _sockfd;
    };
    class TcpSocket : public Socket
    {
    public:
        TcpSocket(int sockfd):_sockfd(sockfd){};
        TcpSocket():_sockfd(defaulted){};
        TcpSocket(std::string& ip,uint16_t port){BuildclientSocket(ip,port);}
        int SocketOrDie() override
        {
            _sockfd = socket(AF_INET, SOCK_STREAM, 0);
           if(_sockfd < 0){
            LOG(LogLevel::ERROR)<<"套接字创建失败";
            exit(1);
           }
           LOG(LogLevel::INFO)<<"套接字创建成功";
            return 0;
        }
        int Connect(std::string& ip,uint16_t port)override{
            NetAddr server(ip,port);
           return connect(_sockfd,(struct sockaddr*)&server.getAddr(),server.getAddrLen());
        }
        ~TcpSocket() {}
        bool BindOrDie(uint16_t port)override
        {
            NetAddr _addr(port);
            int ret=bind(_sockfd,(struct sockaddr*)&_addr.getAddr(),_addr.getAddrLen());
            if(ret < 0){
                LOG(LogLevel::ERROR)<<"套接字绑定失败";
                return false;
            }
            LOG(LogLevel::INFO)<<"套接字绑定成功";
            return true;
        }
        bool ListenOrDie(int backlog=10)override
        {
            int ret=listen(_sockfd,backlog);
            if(ret < 0){
                LOG(LogLevel::ERROR)<<"套接字监听失败";
                return false;
            }
            LOG(LogLevel::INFO)<<"套接字监听成功";
            return true;
        };
        std::shared_ptr<Socket> Accept(NetAddr*client)override
        {
            struct sockaddr_in client_addr;
            socklen_t client_len=sizeof(client_addr);
            int fd=accept(_sockfd,(struct sockaddr*)&client_addr,&client_len);
            if(fd < 0){
                //LOG(LogLevel::ERROR)<<"accept失败...";
                return nullptr;
            }
            client->SetAddr(client_addr);
            return std::make_shared<TcpSocket>(fd);
        };
        void Close()override
        {
            if(_sockfd > 0) close(_sockfd);
        }
        int Recv(std::string *in)override
        {
            char buffer[1024];
            ssize_t n=recv(_sockfd,buffer,sizeof(buffer)-1,0);
            // if(n < 0){
            //     if(errno==EINTR||errno==EAGAIN){
            //         return "";
            //     }
            //     LOG(LogLevel::ERROR)<<"接收数据失败";
            //     return false;
            // }else if(n==0){
            //     LOG(LogLevel::INFO)<<"客户端断开连接";
            //     return false;
            // }
            if(n>0){
            buffer[n]=0;
            *in+=buffer;
            }
            return n;
        };
        bool Send(const std::string &out)override{
            ssize_t n=send(_sockfd,out.c_str(),out.size(),0);
            if(n < 0){
                if(errno==EINTR||errno==EAGAIN){
                    return "";
                }
                LOG(LogLevel::ERROR)<<"发送数据失败";
                return false;
            }else if(n==0){
                LOG(LogLevel::INFO)<<"客户端断开连接";
                return false;
            }
            return true;
        }
    private:
        int _sockfd;//listenfd,sockfd
        
    };
    // class UdpSocket:public Socket{

    // };
}